<?php

namespace app\common\business;

use app\common\model\Article as ArticleModel;
use app\common\model\Attribute as AttributeModel;
use app\common\model\Category as CategoryModel;
use Exception;

class Article extends CommonBase
{
    private $_articleObj = null;

    public function __construct(string $websiteCode, $name)
    {
        $this->_articleObj  = new ArticleModel([], $websiteCode, 'article_' . $name);
        $this->_websiteCode = $websiteCode;
    }

    public function getArticleList(string $cdnDomain, int $page = 1, int $limit = 10, array $where = [], int $flagId = 0, string $attribute = ''): array
    {
        $rows  = [];
        $count = 0;
        try {
            if ($flagId) {
                $filterFlagArticleIds = [];
                $articleFlags         = $this->_articleObj->getFlagIdByFlagId($flagId)->toArray();
                foreach ($articleFlags as $articleFlag) {
                    $filterFlagArticleIds[] = $articleFlag['aid'];
                }
                $where[] = ['p.id', 'in', $filterFlagArticleIds];
            }

            $count = $this->_articleObj->getArticleCount($where, $attribute);
            if (!$count) {
                return ['rows' => $rows, 'count' => $count];
            }

            $totalPage = 1;
            if ($limit != 0) {
                $totalPage = intval(($count / $limit));
                if ($count % $limit != 0) {
                    $totalPage++;
                }
            }

            if ($page > $totalPage) {
                $page = $totalPage;
            }

            if ($page < 1) {
                $page = 1;
            }

            $order = ['p.sort' => 'desc', 'p.created_at' => 'desc'];
            $rows  = $this->_articleObj->getArticleList($page, $limit, $where, $order, $attribute)->toArray();

            $aids = [];
            foreach ($rows as $row) {
                $aids[] = $row['id'];
            }

            // 文档图集
            $articleImages = $this->_articleObj->getArticleImages($cdnDomain, $aids);

            // 文档属性
            $articleRelationAttributes   = $this->_articleObj->getArticleRelationAttributes($aids)->toArray();
            $articleRelationAttributeMap = [];
            foreach ($articleRelationAttributes as $item) {
                $articleRelationAttributeMap[$item['aid']][] = $item;
            }

            // 扩展字段
            $extends = $this->_articleObj->getArticleListExtendFields($cdnDomain, $aids, $rows[0]['category_id']);
            // print_r($extends);

            // 文档标签
            $articleFlags   = $this->_articleObj->getFlagIdByArticleIds($aids)->toArray();
            $articleFlagIds = [];
            $flagModel      = new \app\common\model\Flag([], $this->_websiteCode);
            $allFlags       = $flagModel->getAllFlag();
            $flags          = [];
            foreach ($allFlags as $allFlag) {
                $flags[$allFlag['id']] = $allFlag;
            }
            foreach ($articleFlags as $articleFlag) {
                if (!isset($flags[$articleFlag['flag_id']])) {
                    continue;
                }

                $flag                                  = $flags[$articleFlag['flag_id']];
                $articleFlagIds[$articleFlag['aid']][] = $flag['name'];
            }

            $categoryModel = new CategoryModel([], $this->_websiteCode);
            $categories    = $categoryModel->getAllCategory($cdnDomain);

            $attributeModel = new AttributeModel([], $this->_websiteCode);

            foreach ($rows as $k => $row) {
                $category = $categories[$row['category_id']] ?? [];
                if (empty($category)) {
                    continue;
                }

                $res                = $attributeModel->getCategoryAttribute($category['id']);
                $categoryAttributes = $res['attributes'];

                $rows[$k]['images']         = $articleImages[$row['id']] ?? [];
                $rows[$k]['fullImage']      = $row['image'] ? $cdnDomain . '/' . $row['image'] : '';
                $rows[$k]['category_title'] = $category['title'] ?? '';
                $rows[$k]['created_date']   = date('Y-m-d', strtotime($row['created_at']));
                $rows[$k]['updated_date']   = date('Y-m-d', strtotime($row['updated_at']));
                $rows[$k]['flag_name']      = isset($articleFlagIds[$row['id']]) && $articleFlagIds[$row['id']] ? implode('，', $articleFlagIds[$row['id']]) : '';
                $extendsFields              = $extends[$row['id']] ?? [];
                $rows[$k]['extend_fields']  = $extendsFields;

                $extendFieldMap = [];
                foreach ($extendsFields as $extendsField) {
                    $extendFieldMap[$extendsField['code']] = $extendsField['field_value'];

                    if ($extendsField['field_type'] == 'editor') {
                        $extendFieldMap[$extendsField['code']] = str_replace('{{cdn_domain}', $cdnDomain, $extendsField['field_value']);
                    }

                    if ($extendsField['field_type'] === 'image' || $extendsField['field_type'] === 'file') {
                        $extendFieldMap[underScoreToCamelCase('full_' . $extendsField['code'])] = $extendsField['fullFieldValue'];
                    }
                }
                $rows[$k]['ext_fields'] = $extendFieldMap;

                $categoryCreateAtStr = date('Ymd', strtotime($category['created_at']));
                $rows[$k]['url']     = sprintf('%s/%s%s.html', $category['uri'], $categoryCreateAtStr, $row['id']);

                $rows[$k]['attributes']    = [];
                $articleRelationAttributes = $articleRelationAttributeMap[$row['id']] ?? [];

                foreach ($articleRelationAttributes as $item) {
                    $curAttribute      = $categoryAttributes[$item['attribute_id']] ?? [];
                    $curAttributeValue = $curAttribute['values'][$item['attribute_value_id']] ?? [];
                    if (empty($curAttribute) || empty($curAttributeValue)) {
                        continue;
                    }

                    $rows[$k]['attributes'][] = [
                        'attribute_id'           => $curAttribute['id'] ?? 0,
                        'attribute_name'         => $curAttribute['name'] ?? '',
                        'attribute_value_remark' => $curAttributeValue['remark'] ?? '',
                        'attribute_value_id'     => $curAttributeValue['attribute_value_id'] ?? 0,
                    ];
                }
            }
        } catch (Exception $e) {
            logErr('读取文档列表失败', sprintf('websiteCode:%s,method:%s,err:%s', $this->_websiteCode, __METHOD__, $e->getMessage()));
        }

        return ['rows' => $rows, 'count' => $count];
    }

    public function getArticleListWithPage(string $cdnDomain, array $category, array $where = [], $page = 1, string $attribute = ''): array
    {
        $limit = $category['page'];
        $res   = $this->getArticleList($cdnDomain, $page, $limit, $where, 0, $attribute);

        $totalPage = 0;
        if ($res['count'] != 0) {
            $totalPage = intval(($res['count'] / $limit));
            if ($res['count'] % $limit != 0) {
                $totalPage++;
            }
        }

        return array_merge($res, [
            'categoryUri' => $category['uri'],
            'totalPage'   => $totalPage,
            'pageSize'    => $limit,
        ]);
    }

    public function addArticle(string $cdnDomain, array $data): array
    {
        try {
            return [self::_RESULT => $this->_articleObj->addArticle($cdnDomain, $data), self::_MESSAGE => self::_ADD_SUCCESS_MESSAGE];
        } catch (Exception $e) {
            logErr('添加文档失败', sprintf('websiteCode:%s,method:%s,err:%s', $this->_websiteCode, __METHOD__, $e->getMessage()));
        }

        return [self::_RESULT => false, self::_MESSAGE => self::_SYSTEM_ERROR_MESSAGE];
    }

    public function findLastArticleSortByCategoryId(int $categoryId): array
    {
        $article = [];
        try {
            $article = $this->_articleObj->findLastArticleSortByCategoryId($categoryId);
        } catch (Exception $e) {
            logErr('读取最新的文档id失败', sprintf('websiteCode:%s,method:%s,err:%s', $this->_websiteCode, __METHOD__, $e->getMessage()));
        }

        if (empty($article)) {
            return [];
        }

        return $article;
    }

    public function findArticleById(string $cndDomain, int $id, array $categories): array
    {
        $article = [];
        try {
            $article = $this->_articleObj->findArticleById($cndDomain, $id, $categories);
        } catch (Exception $e) {
            logErr('通过主键读取文档详细信息失败', sprintf('websiteCode:%s,method:%s,err:%s', $this->_websiteCode, __METHOD__, $e->getMessage()));
        }

        if (empty($article)) {
            return [];
        }

        return $article;
    }

    public function mergeNormalAttribute(array $articleAttributes, array $categoryAttributes): array
    {
        // dump($articleAttributes);
        // dump($categoryAttributes);
        $res = [];
        foreach ($categoryAttributes as $categoryAttribute) {
            if ($categoryAttribute['attribute_type'] == AttributeModel::IS_PICTURE_ATTRIBUTE) {
                continue;
            }
            $isMatched = false;
            foreach ($articleAttributes as $articleAttribute) {
                if ($articleAttribute['attribute_id'] == $categoryAttribute['id']) {
                    $res []    = $articleAttribute;
                    $isMatched = true;
                    break;
                }
            }

            if (!$isMatched) {
                $res [] = [
                    'attribute_id'       => $categoryAttribute['id'],
                    'name'               => $categoryAttribute['name'],
                    'options'            => $categoryAttribute['values'],
                    'attribute_value_id' => [],
                ];
            }
        }
        return $res;
    }

    public function updateArticle(string $cdnDomain, int $id, array $data): array
    {
        try {
            return [self::_RESULT => $this->_articleObj->updateArticle($cdnDomain, $id, $data), self::_MESSAGE => self::_UPDATE_SUCCESS_MESSAGE];
        } catch (Exception $e) {
            logErr('通过主键更新文档信息失败', sprintf('websiteCode:%s,method:%s,err:%s', $this->_websiteCode, __METHOD__, $e->getMessage()));
        }

        return [self::_RESULT => false, self::_MESSAGE => self::_SYSTEM_ERROR_MESSAGE];
    }

    public function deleteArticle(int $id, array $fields): array
    {
        try {
            return [self::_RESULT => $this->_articleObj->deleteArticle($id, $fields), self::_MESSAGE => self::_DELETE_SUCCESS_MESSAGE];
        } catch (Exception $e) {
            logErr('通过主键删除文档失败', sprintf('websiteCode:%s,method:%s,err:%s', $this->_websiteCode, __METHOD__, $e->getMessage()));
        }

        return [self::_RESULT => false, self::_MESSAGE => self::_SYSTEM_ERROR_MESSAGE];
    }

    public function batchArticleSort(array $data): array
    {
        try {
            return [self::_RESULT => $this->_articleObj->batchArticleSort($data), self::_MESSAGE => self::_SORT_SUCCESS_MESSAGE];
        } catch (Exception $e) {
            logErr('通过主键更新文档排序失败', sprintf('websiteCode:%s,method:%s,err:%s', $this->_websiteCode, __METHOD__, $e->getMessage()));
        }

        return [self::_RESULT => false, self::_MESSAGE => self::_SYSTEM_ERROR_MESSAGE];
    }

    public function batchDeleteArticle(array $ids, array $fields): array
    {
        try {
            return [self::_RESULT => $this->_articleObj->batchDeleteArticle($ids, $fields), self::_MESSAGE => self::_DELETE_SUCCESS_MESSAGE];
        } catch (Exception $e) {
            logErr('通过主键批量删除文档失败', sprintf('websiteCode:%s,method:%s,err:%s', $this->_websiteCode, __METHOD__, $e->getMessage()));
        }

        return [self::_RESULT => false, self::_MESSAGE => self::_SYSTEM_ERROR_MESSAGE];
    }

    public function batchUpdateArticleStatus(array $ids, int $status): array
    {
        try {
            return [self::_RESULT => $this->_articleObj->batchUpdateArticleStatus($ids, $status), self::_MESSAGE => self::_UPDATE_SUCCESS_MESSAGE];
        } catch (Exception $e) {
            logErr('通过主键批量更新文档状态失败', sprintf('websiteCode:%s,method:%s,err:%s', $this->_websiteCode, __METHOD__, $e->getMessage()));
        }

        return [self::_RESULT => false, self::_MESSAGE => self::_SYSTEM_ERROR_MESSAGE];
    }

    public function batchUpdateArticleFlagId(array $ids, int $operate, $flagId): array
    {
        try {
            return [self::_RESULT => $this->_articleObj->batchUpdateArticleFlagId($ids, $operate, $flagId), self::_MESSAGE => self::_UPDATE_SUCCESS_MESSAGE];
        } catch (Exception $e) {
            logErr('通过主键批量更新文档标签失败', sprintf('websiteCode:%s,method:%s,err:%s', $this->_websiteCode, __METHOD__, $e->getMessage()));
        }

        return [self::_RESULT => false, self::_MESSAGE => self::_SYSTEM_ERROR_MESSAGE];
    }

    public function getPrevAndNextArticle(int $id): array
    {
        $prev = [];
        $next = [];
        if (!$id) {
            return ['prev' => [], 'next' => []];
        }

        try {
            $article = $this->_articleObj->findArticleWithoutExtendFieldsById($id);
            if (empty($article)) {
                return ['prev' => [], 'next' => []];
            }

            // 所有栏目列表
            $categoryModel = new CategoryModel([], $this->_websiteCode);
            $categories    = $categoryModel->getAllCategory();
            $category      = $categories[$article['category_id']] ?? [];
            if (empty($category)) {
                return ['prev' => [], 'next' => []];
            }

            $categoryCreateAtStr = date('Ymd', strtotime($category['created_at']));
            $prevAndNext         = $this->_articleObj->getPrevAndNextArticle($article['sort'], ['category_id' => $article['category_id'], ['id', '<>', $id]]);

            $prev = $prevAndNext['prev'] ? $prevAndNext['prev']->toArray() : [];
            if (!empty($prev)) {
                $prev['url'] = sprintf('%s/%s%s.html', $category['uri'], $categoryCreateAtStr, $prev['id']);
            }

            $next = $prevAndNext['next'] ? $prevAndNext['next']->toArray() : [];
            if (!empty($next)) {
                $next['url'] = sprintf('%s/%s%s.html', $category['uri'], $categoryCreateAtStr, $next['id']);
            }
        } catch (\Exception $e) {
            logErr('通过主键读取文档上一篇、下一篇失败', sprintf('websiteCode:%s,method:%s,err:%s', $this->_websiteCode, __METHOD__, $e->getMessage()));
        }

        return [
            'prev' => $prev,
            'next' => $next,
        ];
    }
}
